import {BaseContract, ethers} from 'ethers'

const defaultsABI = [
  // Some details about the token
  // 代币信息
  'function name() view returns (string)',
  'function symbol() view returns (string)',
  "function decimals() view returns (uint8)",

  // Get the account balance
  // 获取指定账户地址的代币余额
  'function balanceOf(address) view returns (uint)',

  // Send some of your tokens to someone else
  // 发送指定数量的代币到指定地址
  'function transfer(address to, uint amount)',

  // 向某个账户地址指定可用代币额度
  'function approve(address spender, unit amount) nonpayable returns (bool)',

  // An event triggered whenever anyone transfers to someone else
  // 该合约的代币发生转账时会触发的事件
  'event Transfer(address indexed from, address indexed to, uint amount)',
];

export default class EthWallet {
  constructor() {
    this.isV5 = !!ethers.providers;
    this.userAddress = undefined;
    this.signer = undefined;
    this.provider = undefined;
    this.walletError = "";
    this.providerUrl = undefined;
    this.ABI = JSON.parse(JSON.stringify(defaultsABI));
    this.tokenContract = undefined;
  }
  // 必须钱包在BSC上面
  async initBSC() {
    const {ethereum} = window;
    console.log(ethereum.chainId);
    if (!ethereum) {
      console.log("please install metamask");
      this.walletError = "";
      return false;
    } else if (ethereum.chainId !== "0x38") {
      await this.toSwitch(56);
      this.initBSC();
      alert("Please connect to the appropriate BSC network.");
      this.walletError = 'Wrong Network';
      return false;
    } else {
      console.log('you have metamask installed');
      this.walletError = "";
    }
    await this.initProviderAndSigner();
    let userAddressList = await this.provider.send("eth_requestAccounts", []);
    console.log(userAddressList);
    this.userAddress = userAddressList[0];
    return true;
  }

  async initAnyChain() {
    const {ethereum} = window;
    console.log(ethereum.chainId)
    if (!ethereum && !this.providerUrl) {
      console.error("please install metamask or setProviderUrl");
      this.walletError = "";
      return false;
    } else {
      console.log('you have metamask installed');
      this.walletError = "";
    }
    await this.initProviderAndSigner(this.providerUrl);
    let userAddressList = await this.provider.send("eth_requestAccounts", []);
    // console.log(userAddressList);
    this.userAddress = userAddressList[0];
    return true;
  }

  async sendBNBTran(toAddress, amountBNB) {
    let tx = {
      to: toAddress,
      // ... or supports ENS names
      // to: "ricmoo.firefly.eth",

      // We must pass in the amount as wei (1 ether = 1e18 wei), so we
      // use this convenience function to convert ether to wei.
      value: ethers.utils.parseEther(amountBNB)
    };
    let res = await this.signer.sendTransaction(tx);
    // console.log(res)
    return res;
  }

  async initProviderAndSigner(url) {
    if(this.isV5) {
      this.provider = new ethers.providers.getDefaultProvider();
      if(url) {
        this.provider = new ethers.providers.JsonRpcProvider(url);
      }
      this.signer = this.provider.getSigner();
      return;
    }
    // v6
    this.provider = new ethers.BrowserProvider(window.ethereum);
    if(url) {
      this.provider = new ethers.JsonRpcProvider(url)
    }
    // console.log(this.provider)
    this.signer = await this.provider.getSigner();
  }

  setProviderUrl(url) {
    this.providerUrl = url;
  }

  setABI(ABI) {
    this.ABI = ABI;
  }

  resetABI() {
    this.ABI = JSON.parse(JSON.stringify(defaultsABI));
  }

  updateTokenContract(tokenAddress){
    if(!this.signer) {
      throw Error(`请检查你的网络`);
    }
    if(!this.ABI || !tokenAddress) {
      throw Error(`请先初始化ABI、以及代币地址`);
    }
    if(this.isV5) {
      this.tokenContract = new ethers.Contract(tokenAddress, this.ABI, this.signer || this.provider);
      return;
    }
    this.tokenContract = new BaseContract(tokenAddress, this.ABI, this.signer);
  }

  async contractFn(fnName, ...args) {
    console.log(args,'contractFn')
    if(!this.tokenContract) {
      throw Error(`请先更新代币合约地址`);
    }
    let result = await this.tokenContract[fnName](...args)
    return result;
  }

  async toSwitch(chainId) {
    try {
        await window['ethereum'].request({
            method: 'wallet_switchEthereumChain',
            params: [{ chainId: '0x' + chainId.toString(16) }]
        }, (err, result) => {
            console.log(err, '添加失败')
            if (err) {
                throw Error('切换主链失败' + err.message);
            }
        });
    } catch (error) {
        throw Error('切换主链失败 - 2' + error.message);
    }
  }
 
async addChain(chainOptions) {
    //  const chainOptions = {
    // 　　chainId: '97',
    // 　　blockBrowseUrl: 'https://testnet.bscscan.com',
    // 　　name: 'Binance Smart Chain Testnet',
    // 　　blockJsonRpcUrl: 'https://endpoints.omniatech.io/v1/bsc/testnet/public',
    // 　　symbol: 'tBNB',
    // 　　decimals: 18,
    // }
    const {
    　　chainId,
    　　blockBrowseUrl,
    　　name,
    　　blockJsonRpcUrl,
    　　symbol,
    　　decimals,
    } = chainOptions;
    chainId = chainId.toString().indexOf('0x')?chainId:'0x' + Number(chainId).toString(16);
　　try {
　　　　await window.ethereum.request({
　　　　　　method: "wallet_addEthereumChain",
　　　　　　params: [
　　　　　　　　{
　　　　　　　　　　chainId: chainId,
　　　　　　　　　　chainName: name,
　　　　　　　　　　nativeCurrency: {
　　　　　　　　　　　　name: symbol,
　　　　　　　　　　　　symbol: symbol,
　　　　　　　　　　　　decimals: decimals,
　　　　　　　　　　},
　　　　　　　　rpcUrls: [blockJsonRpcUrl],
　　　　　　　　blockExplorerUrls: [blockBrowseUrl],
　　　　　　　},
　　　　　],
　　　　});
　　} catch (error) {
　　　　console.log("添加网络失败", error.message);
　　}
}
}
